package com.itheima.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.itheima.constant.MessageConstant;
import com.itheima.entity.PageResult;
import com.itheima.entity.QueryPageBean;
import com.itheima.entity.Result;
import com.itheima.exceptions.BusinessException;
import com.itheima.pojo.Menu;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import com.itheima.utils.EmailUtils;
import com.itheima.utils.ValidateCodeUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author W.J.Y
 */
@RestController
@RequestMapping("user")
public class UserController {

    @Reference(version = "1.0.0")
    private UserService userService;
    @Resource
    private JedisPool jedisPool;


    @GetMapping("getUser")
    public Result getUser(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails principal = (UserDetails) authentication.getPrincipal();
        return new Result(true,null,principal.getUsername());
    }

    /**
     * 发送验证码的方法
     * @return
     */
    @GetMapping("sendValidateCode")
    public Result sendValidateCode(){
        //获取登录的用户的用户名
        Result result = this.getUser();
        String username = (String)result.getData();
        User loginUser = userService.findUserByUserName(username);
        Jedis resource = null;
        try {
            //发送验证码
            Integer code = ValidateCodeUtils.generateValidateCode(6);
            System.out.println("修改密码验证码：" + code);
            EmailUtils.sendMail(loginUser.getEmail(),"您即将要修改传智健康系统的登录密码，" +
                    "验证码为："+code+"。如不是本人操作，请忽略本邮件","传智健康用户修改密码");
            //将邮箱验证码存入redis中，失效时间5分钟
            resource = jedisPool.getResource();
            resource.setex("CHANGEPWD_" + username, 5 * 60, code.toString());
            return new Result(true, MessageConstant.SEND_VALIDATECODE_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(MessageConstant.SEND_VALIDATECODE_FAIL);
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
    }


    /**
     * 修改密码的方法
     * @return
     */
    @PostMapping("changePassword")
    public Result changePassword(@RequestBody Map<String,String> map){
        //获取验证码并与数据库进行比对
        String code = map.get("code");
        String password = map.get("password");
        //获取登录的用户的用户名
        Result result = this.getUser();
        String username = (String)result.getData();
        Jedis client = jedisPool.getResource();
        String getCode = client.get("CHANGEPWD_" + username);
        client.close();
        if (getCode == null || !code.equals(code)) {
            return new Result(false, MessageConstant.VALIDATECODE_ERROR);
        }
        //验证码验证通过，修改密码
        userService.changePassword(password,username);
        return new Result(true, "密码修改成功!");
    }






    /**
     * 根据用户名拉取菜单数据
     * @param username 用户名
     * @return  菜单数据
     */
    @RequestMapping("getMenus/{username}")
    public Result getMenus(@PathVariable String username){
        List<Menu> menus = userService.findMenusByUserName(username);
        return new Result(true,"拉取菜单完成！",menus);
    }

    /**
     * 新增用户
     * @param user  用户实例
     * @return  统一返回结果
     */
    @RequestMapping("add")
    @PreAuthorize("hasAuthority('USER_ADD')")
    public Result add(@RequestBody User user){
        //调用业务层添加方法
        userService.add(user);
        //返回操作结果
        return new Result(true, "新增用户成功！");
    }


    /**
     * 编辑用户
     * @param user  用户实例
     * @return  统一返回结果
     */
    @RequestMapping("update")
    @PreAuthorize("hasAuthority('USER_EDIT')")
    public Result update(@RequestBody User user){
        //调用业务层修改方法
        userService.update(user);
        //
        //返回操作结果
        return new Result(true, "修改成功！");
    }

    /**
     * 根据ID删除用户
     * @param id    用户ID
     * @return  返回结果
     */
    @GetMapping("delete/{id}")
    @PreAuthorize("hasAuthority('USER_DELETE')")
    public Result delete(@PathVariable int id){
        //调用业务层删除方法
        userService.delete(id);
        //返回操作结果
        return new Result(true, "用户删除成功！");
    }

    /**
     * 根据ID查询用户信息
     * @param id    用户ID
     * @return  返回结果
     */
    @RequestMapping("findById/{id}")
    public Result findById(@PathVariable int id){
        User user = userService.findById(id);
        return new Result(true,"查询用户信息成功！",user);
    }

    /**
     * 分页查询用户数据
     * @param queryPageBean 分页查询语句
     * @return  返回结果
     */
    @RequestMapping("findPage")
    @PreAuthorize("hasAuthority('USER_QUERY')")
    public PageResult findPage(@RequestBody QueryPageBean queryPageBean){
        PageResult pageResult = userService.findPage(
                queryPageBean.getCurrentPage(),
                queryPageBean.getPageSize(),
                queryPageBean.getQueryString());
        return pageResult;
    }

    public void changeAuthority(){
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        List<GrantedAuthority> updatedAuthorities = new ArrayList<>(auth.getAuthorities());
        updatedAuthorities.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return null;
            }
        }); //add your role here [e.g., new SimpleGrantedAuthority("ROLE_NEW_ROLE")]

        Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);

        SecurityContextHolder.getContext().setAuthentication(newAuth);
    }

}